package cn.lr.basic.service.impl;

import cn.lr.basic.Exception.BusinessException;
import cn.lr.basic.constant.BaseConstants;
import cn.lr.basic.service.IVerifyCodeService;
import cn.lr.basic.util.StrUtils;
import cn.lr.basic.util.VerifyCodeUtils;
import cn.lr.basic.dto.RegisterDto;
import cn.lr.user.domain.User;
import cn.lr.user.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.concurrent.TimeUnit;

@Service
public class VerifyCodeServiceImpl implements IVerifyCodeService {

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private UserMapper userMapper;

    /**
     * 图形验证码
     * @param key
     * @return
     */
    @Override
    public String graph(String key) {
        //1.判断key不为空
        if(!StringUtils.hasLength(key)){
            throw  new BusinessException("请输入key");
        }
        //2.使用UUID生成一个图片验证码的值
        String code = StrUtils.getComplexRandomString(4);
        //3.把验证码的值存储到Redis,以前台传入的key作为key
        redisTemplate.opsForValue().set(key,code,5, TimeUnit.MINUTES);
        //4.把验证码的值合并到图片
        //5.把图片使用Base64编码
        //6.返回base64编码的字符串
        return VerifyCodeUtils.VerifyCode(108,34,code);
    }

    private void sendRegisterCode(RegisterDto dto){
        // 1.校验参数
        // 空校验
        String phone = dto.getPhone();
        String imageCodeValue = dto.getImageCodeValue();
        String imageCodeKey = dto.getImageCodeKey();
        if(phone == null || imageCodeValue == null || imageCodeKey == null){
            throw new BusinessException("请填写手机号或验证码");
        }
        // 检验手机号是否已经被注册
        User user = userMapper.loadByPhone(dto.getPhone());
        if (user != null) {
            throw new BusinessException("手机号已被注册，请直接返回登录");
        }
        // 2.图形验证码校验，根据imageCodeKey从redis中获取图形验证码
        Object imageCodeTemp = redisTemplate.opsForValue().get(imageCodeKey);
        // 没有拿到，验证码已失效,报错
        if(imageCodeTemp == null){
            throw new BusinessException("验证码已失效，请重新获取");
        }
        // 拿到了，判断输入的验证码是否正确
        if(!imageCodeTemp.toString().equalsIgnoreCase(imageCodeValue)){
            throw new BusinessException("请输入正确的验证码");
        }
        String businessKey = BaseConstants.VerifyCodeConstants.BUSINESS_REGISTER_PREFIX + phone;
        sendSmsCode(businessKey);


    };

    /**
     *  微信绑定验证码
     * @param dto
     */
    private void sendBinderCode(RegisterDto dto){
        String businessKey = BaseConstants.VerifyCodeConstants.BUSINESS_BINDER_PREFIX + dto.getPhone();
        sendSmsCode(businessKey);
    };

    /**
     *
     * @param businessKey
     */
    public void sendSmsCode( String businessKey){
        String smsCodeKey = businessKey;
        // 根据key 获取value值--验证码：时间戳
        Object smsCodeTemp = redisTemplate.opsForValue().get(smsCodeKey);
        String smsCode = "";
        if(smsCodeTemp != null){
            // 获取到了，判断是否超过了重发时间1分钟
            Long oldTime = Long.valueOf(smsCodeTemp.toString().split(":")[1]);
            // 小于一分钟，报错，请勿重复获取验证码
            if(System.currentTimeMillis()-oldTime <= 1*60*1000){
                throw new BusinessException("请不要重复获取验证码");
            }
            // 大于一分钟，使用原来的验证码
            smsCode = smsCodeTemp.toString().split(":")[0];
        } else {
            // 获取不到，说明验证码已经过期，直接重新生成验证码
            smsCode = StrUtils.getComplexRandomString(4);
        }
        // 5,保存redis,设置过期时间为三分钟，刷新过期时间
        String smsCodeValue = smsCode + ":" + System.currentTimeMillis();
        redisTemplate.opsForValue().set(smsCodeKey, smsCodeValue, 3, TimeUnit.MINUTES);
        // 6.发送短信验证码
        System.out.println("您的验证码是" + smsCode + "请在三分钟有效期内使用");
    }

    @Override
    public void smsCode(RegisterDto dto) {
        String type = dto.getType();
        if("register".equals(type)){
            sendRegisterCode(dto);
        } else {
            sendBinderCode(dto);
        }
    }
}
